package com.retail.bbq.cola.aop;

import com.alibaba.fastjson.JSONObject;
import com.retail.bbq.cola.config.NeedCryptoConfig;
import com.retail.bbq.cola.utils.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 请求响应处理类
 * 对加了@Encrypt的方法的数据进行加密操作
 *
 * @author gzy
 */
@ControllerAdvice
@Slf4j
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Value("${aes.key}")
    public String aesKsy;
    @Value("${aes.iv}")
    public String aesIv;
    public static final String DATA_STR = "data";

    public static final String CRYPT_STR = "crypt";

    public static final String ENCRYPT_HEADER = "encrypt";

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return new NeedCryptoConfig().isNeedEncrypt(returnType);
    }


    //这个方法截取了接口中返回的对象，在对对象加密后返回xxxxxxxxxx
    @Override
    public Object beforeBodyWrite(Object obj, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        ServletServerHttpRequest sshr = (ServletServerHttpRequest) serverHttpRequest;
        HttpServletRequest request = sshr.getServletRequest();

        String returnData = "";
        String realData = "";
        JSONObject data = new JSONObject();
        try {
            data = (JSONObject) JSONObject.toJSON(obj);
            Object dataObj = data.get(DATA_STR);
            if(Objects.nonNull(dataObj) && !StringUtils.isBlank(dataObj.toString())){
                realData = data.get(DATA_STR).toString();
            }
            // header添加encry，告诉前端数据已加密
            serverHttpResponse.getHeaders().add(ENCRYPT_HEADER, "true");
            // 加密
            if(StringUtils.isNotBlank(realData)){
                returnData = AesUtil.encryptBase64(realData, aesKsy, aesIv);
                log.debug("接口={},原始数据={},加密后数据={}", request.getRequestURI(), realData, returnData);
            }
            data.put(DATA_STR, returnData);
            data.put(CRYPT_STR, new NeedCryptoConfig().isNeedEncrypt(returnType));
        } catch (Exception e) {
            log.error("接口返回结果加密异常！", e);
        }
        return data;
    }
}
